var OPENSTREETMAP = OPENSTREETMAP || {};

OPENSTREETMAP.TrafficStream = function(scene,timeAndPath,width,color,secondSpentInOneFrame,fadeRate) {
    this.initialize(scene,timeAndPath,width,color,secondSpentInOneFrame,fadeRate);
};

OPENSTREETMAP.TrafficStream.prototype = {
    //Must afferent
    scene : null,
    timeAndPath: null,
    //timeAndPath : [[0, [-1000, -1000, 0]], [300, [-1000, 1000, 0]], [700, [1000, 1000, 0]], [800, [1000, -1000, 0]], [1200, [0, 0, 0]]],
   
    //Better
    width : 100,
    color : "FFFFFF",
    secondSpentInOneFrame:3, 
    fadeRate: 0.02,
        
    //Calculated
    scale : 0,
    linkInfo: null,
    
    secondNow: 0,
    
    linkIndexNow: 0,
    vectoryNow: 0,
    positionNow:0,
    isActived: true,
    
    material1:null,material2:null,material3:null,
    headRowPaticlesCount: 0,

    initialize : function(scene,timeAndPath,width,color,secondSpentInOneFrame,fadeRate) {
        this.scene = scene;
        this.timeAndPath = timeAndPath;
        
        this.width = width || this.width; 
        this.color = (new THREE.Color(color).getHexString()) || this.color;       
        this.secondSpentInOneFrame = secondSpentInOneFrame || this.secondSpentInOneFrame;   
        this.fadeRate = fadeRate || this.fadeRate;    
    
        this.GetLinkInfo();
        this.scale = this.width;
        this.getMaterials(); 
        
    },
    
    start:function(){
      
        this.group = new THREE.Object3D();
        this.scene.add(this.group);

        this.updateParticles(this.secondNow);
    },

    update : function() {    
     
        if(!this.isActived){
            return;
        }
        
        if(this.time != 0 && this.group.children.length == 0){
            this.isActived = false;
            this.clear();
            console.log("finish");
        }
        
        this.secondNow += this.secondSpentInOneFrame;
        this.updateParticles(this.secondNow);
        
        this.fadeAndRemoveParticles();       

    },
    
    getActiveStatus: function(){
      return this.actived; 
    },

    updateParticles: function(secondNow){

        var neededNewLine = false;
       if (secondNow <= this.linkInfo[this.linkInfo.length-1][1]) {
            neededNewLine = true;
        }
        else {
           neededNewLine = false;
        }

        //Add one line of particles
        if (neededNewLine) {
            var newPositions = this.getNewPositions(secondNow);
  
            if (newPositions != null) {
                for(var j =0;j<newPositions.length;j++){   
                                                                
                    var material = this.material1.clone();
                    
                    if(j==0){
                        for(var i =0;i<this.headRowPaticlesCount;i++){
                        var headRowMaterial = material.clone();
                        var headRowPaticle = new THREE.Sprite(headRowMaterial);
                        headRowPaticle.position.x = newPositions[j][0];// + (Math.random()-1)*this.width;
                        headRowPaticle.position.y = newPositions[j][1];// + (Math.random()-1)*this.width;
                        headRowPaticle.position.z = newPositions[j][2];// + (Math.random()-1)*this.width;
                        headRowPaticle.scale.x = headRowPaticle.scale.y =  this.scale;
                        headRowPaticle.material.opacity = -1.0;
                        this.group.add(headRowPaticle);
                        }
                    }
                    
                    var particle = new THREE.Sprite(material);
                    particle.position.x = newPositions[j][0];// + (Math.random()-1)*this.width;
                    particle.position.y = newPositions[j][1];// + (Math.random()-1)*this.width;
                    particle.position.z = newPositions[j][2];// + (Math.random()-1)*this.width;
                    particle.scale.x = particle.scale.y =  this.scale;
                    this.group.add(particle);
                    
                }               
            }
        }
    },

    fadeAndRemoveParticles : function() {
        for (var i = this.group.children.length-1; i >=0; i--) {
            this.group.children[i].material.opacity -= this.fadeRate;
            this.group.children[i].scale.x = this.group.children[i].scale.y = this.scale * Math.sqrt(this.group.children[i].material.opacity);

            if (this.group.children[i].material.opacity < 0.01) {
                this.group.remove(this.group.children[i]);
            }
        }
    },
    
    getNewPositions: function(secondNow){
        var newPositions = [];
        var linkIndex = 0;
         for (var i = 0; i < this.linkInfo.length; i++) {
             if (secondNow >= this.linkInfo[i][1]) {
                linkIndex = i+1;
                continue;
             }
             break;
         }
         if (linkIndex>= this.linkInfo.length) {
              return null;
         }
        var timeNeeded = this.linkInfo[linkIndex][1] - secondNow;
        var distenceNeeded = this.linkInfo[linkIndex][2] * timeNeeded;
        var unitDirection = 
        [(this.linkInfo[linkIndex][5][0] - this.linkInfo[linkIndex][4][0])/this.linkInfo[linkIndex][3],
        (this.linkInfo[linkIndex][5][1] - this.linkInfo[linkIndex][4][1])/this.linkInfo[linkIndex][3],
        (this.linkInfo[linkIndex][5][2] - this.linkInfo[linkIndex][4][2])/this.linkInfo[linkIndex][3],
        ];
            
        var distenceInThisDuration = this.linkInfo[linkIndex][2]*this.secondSpentInOneFrame;
        for(var i = 0; i < distenceInThisDuration;){
            
            if(distenceNeeded+i>this.linkInfo[linkIndex][3] && linkIndex>0){
                break;
            }          
            var newPosition = [
                    this.linkInfo[linkIndex][4][0] + unitDirection[0]*(distenceNeeded + i),
                    this.linkInfo[linkIndex][4][1] + unitDirection[1]*(distenceNeeded + i),
                    this.linkInfo[linkIndex][4][2] + unitDirection[2]*(distenceNeeded + i)
               ];

            i += this.scale/10;            
            newPositions.push(newPosition);
        }

        return newPositions;
    },

    clear : function() {
        for (var i = 0; i < this.group.children.length; i++) {
            this.group.remove(this.group.children[i]);
        }
        this.scene.remove(this.group);
    },
     
    console : function() {
        //console.log(this.group);
        //console.log(this.group.id);
        //console.log(this.group.children[0]);
        //console.log(this.group.children[0].position.x);
        //console.log(this.timeAndPath);
        //console.log(this.timeAndPath.length);
        //console.log(this.timeAndPath[1][0] - this.timeAndPath[0][0] );
    },
  
    generateSprite : function() {

        //Circle
        var canvas = document.createElement('canvas');
        canvas.width = 16;
        canvas.height = 16;

        var context = canvas.getContext('2d');
        var gradient = context.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2);

        gradient.addColorStop(0, 'rgba(255,255,255,1)');
        gradient.addColorStop(0.16, this.color);
        gradient.addColorStop(0.5, 'rgba(0,0,0,0.5)');
        gradient.addColorStop(1, 'rgba(0,0,0,0.0)');
        
        /*
        gradient.addColorStop(0, 'rgba(255,255,255,1)');
        gradient.addColorStop(0.16, this.color);
        gradient.addColorStop(0.5, 'rgba(0,0,0,0.2)');
        gradient.addColorStop(1, 'rgba(255,255,255,0.0)');*/


        context.fillStyle = gradient;
        context.fillRect(0, 0, canvas.width, canvas.height);
        //context.arc(canvas.width/2, canvas.width/2, canvas.width/2, 0, 2*Math.PI, true);
        context.fill();

        return canvas;
        
        /*
        //Rect
        var canvas = document.createElement('canvas');
        canvas.width = 128;
        canvas.height = 128;

        var context = canvas.getContext('2d');
        context.fillStyle = "#ff000f";
        context.strokeStyle = "white";
        context.fillRect(0, 0, 63, 63);

        return canvas;
        */
    },
    
    getMaterials: function(){
        
            var particleTexture = new THREE.Texture(this.generateSprite());
            particleTexture.needsUpdate = true;
            
            this.material1 = new THREE.SpriteMaterial({
                //color useful in WebGLRenderer Mode
                color: 0x0000ff,
                map : particleTexture,
                opacity : 1.0,
                blending : THREE.AdditiveBlending,
                 //transparent: true,
                 fog:200,
            });

            // 创建粒子基本材质
            this.material2 =
              new THREE.SpriteMaterial({
                color: 0xff0000,
                size: 16,
                map: THREE.ImageUtils.loadTexture(
                  "images/particle.png"
                ),
                opacity:1,
                blending: THREE.AdditiveBlending,
                depthWrite: false,
                needsUpdate: false,
                transparent: false,
              });
                               
            var PI2 = Math.PI * 2;
            var program = function(context) {
                context.beginPath();
                context.arc(0, 0, 0.5, 0, PI2, true);
                context.fill();
            };
    
             this.material3 = new THREE.SpriteCanvasMaterial({
             color : Math.random() * 0x808008 + 0x808080,
             //color : 0xff0000,
             program : program,
             blending: THREE.AdditiveBlending,
             fog : true
             });
                
            //console.log(this.material1);
            //console.log(this.material2);                    
    },

    GetLinkInfo : function() {

        this.linkInfo = [];

        for (var linkIndex = 0; linkIndex < this.timeAndPath.length-1; linkIndex++) {
            var distence = Math.sqrt((this.timeAndPath[linkIndex+1][1][0] - this.timeAndPath[linkIndex][1][0]) * (this.timeAndPath[linkIndex+1][1][0] - this.timeAndPath[linkIndex][1][0]) + (this.timeAndPath[linkIndex+1][1][1] - this.timeAndPath[linkIndex][1][1]) * (this.timeAndPath[linkIndex+1][1][1] - this.timeAndPath[linkIndex][1][1]) + (this.timeAndPath[linkIndex+1][1][2] - this.timeAndPath[linkIndex][1][2]) * (this.timeAndPath[linkIndex+1][1][2] - this.timeAndPath[linkIndex][1][2]));
            var duration = this.timeAndPath[linkIndex+1][0] - this.timeAndPath[linkIndex][0];
            var vectory = 0;
            if (duration > 0 && distence > 0) {
              vectory = distence / duration;
            }

            var endTimeStamp = this.timeAndPath[linkIndex+1][0] - this.timeAndPath[0][0];
            var oneLinkInfo = [duration, endTimeStamp, vectory, distence, this.timeAndPath[linkIndex+1][1], this.timeAndPath[linkIndex][1]];

            this.linkInfo.push(oneLinkInfo);
        }
    },
};